package com.peacock.feather.utility;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.junit.Test;
import org.springframework.util.CollectionUtils;


/**
 * dom4j工具类<br>
 * 
 * @author 项硕
 */
public class XDom4jUtils {

	/**
	 * 根据格式，将xml写入文件
	 * @param filename
	 * @param doc
	 * @param format
	 * @throws IOException
	 */
	public static void write(String filename, Document doc, OutputFormat format) throws IOException {
		try {
			XMLWriter out = null;
			try {
				out = null == format ? 
						new XMLWriter(new FileWriter(filename)) : new XMLWriter(new FileWriter(filename), format);
				out.write(doc);
			} finally {
				if (null != out) out.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
			throw e;
		}
	}

	/**
	 * 将xml写入文件
	 * @param filename
	 * @param doc
	 * @throws IOException
	 */
	public static void write(String filename, Document doc) throws IOException {
		write(filename, doc, null);
	}
	
	/**
	 * 根据命名空间读取xml文件
	 * @param filename
	 * @param xpathNamespaceURIMap
	 * @return
	 * @throws DocumentException
	 */
	public static Document read(String filename, Map<String, String> xpathNamespaceURIMap) 
			throws DocumentException {
		SAXReader reader = new SAXReader();
		if (! CollectionUtils.isEmpty(xpathNamespaceURIMap)) {
			reader.getDocumentFactory().setXPathNamespaceURIs(xpathNamespaceURIMap);
		}
		try {
			return reader.read(new File(filename));
		} catch (DocumentException e) {
			e.printStackTrace();
			throw e;
		}
	}
	
	/**
	 * 读取xml文件
	 * @param filename
	 * @return
	 * @throws DocumentException
	 */
	public static Document read(String filename) throws DocumentException {
		return read(filename, null);
	}
	
	/* ---------------------------------------- test ---------------------------------------- */
	
	@Test
	public void testWrite() {
		String filename = "src/main/resources/xml/out.xml";
		
		Document doc = DocumentHelper.createDocument();	// 创建doc
		
		Element root = doc.addElement("root");
		root.addElement("student").addAttribute("name", "项硕")
			.addElement("signature").addText("前途无量");
		
		OutputFormat format = OutputFormat.createPrettyPrint();	// 指定打印格式
		try {
			XDom4jUtils.write(filename, doc, format);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Test
	@SuppressWarnings("unchecked")
	public void testRead1() {	//无命名空间
		String filename = "src/main/resources/xml/in-without-namespace.xml";
		
		try {
			Document doc = XDom4jUtils.read(filename);
			Element root = doc.getRootElement();	// 根元素
			System.out.println("根元素：\n" + root.asXML() + "\n");
			
			Element son = (Element) root.selectSingleNode("student[@name='项邵泷']");
			System.out.println("项邵泷：\n" + son.asXML() + "\n");
			
			List<Element> signatureList = (List<Element>) root.selectNodes("//signature");
			System.out.println("所有签名：");
			for (Element elem : signatureList) {
				System.out.println(elem.asXML());
			}
			System.out.println();
		} catch (DocumentException e) {
			e.printStackTrace();
		}
	}

	@Test
	public void testRead2() {	//有命名空间
		String filename = "src/main/resources/xml/in-with-namespace.xml";
		
		Map<String, String> nsMap = new HashMap<String, String>();
		nsMap.put("ns", "http://maven.apache.org/POM/4.0.0");
		try {
			Document doc = XDom4jUtils.read(filename, nsMap);
			Element root = doc.getRootElement();	// 根元素
			System.out.println("根元素：\n" + root.asXML() + "\n");
			
			Element servlet = (Element) root.selectSingleNode("//ns:dependency[ns:groupId='javax.servlet']");
			System.out.println("servlet：\n" + servlet.asXML() + "\n");
			
			servlet = (Element) root.selectSingleNode("//ns:dependency[@data='xxx']");	// 属性前不需要加命名空间
			System.out.println("servlet-属性查询：\n" + servlet.asXML() + "\n");
		} catch (DocumentException e) {
			e.printStackTrace();
		}
	}
}
